package com.ivsign.lib_idcardidentification;

import android.util.Log;

import com.clj.fastble.utils.HexUtil;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Arrays;


/**
 * @description :
 * @autHor :  Jason
 * @date : 2018/8/17 16:56
 */

public class SocketCommunication {


    private static final String LOGTAG = "SocketLog";
    private Socket Tcpsocket;
    private OutputStream TcpSocketOut;
    private InputStream TcpSocketIn;

    private IDCardCommunication idCardCommunication;
    private MainHandler mHandler;

    public SocketCommunication(IDCardCommunication idCardCommunication, MainHandler handler) {
        this.idCardCommunication = idCardCommunication;
        this.mHandler = handler;
    }

    public int TcpInit(String serverIP, int serverPort) {
        try {
            // ���ӷ����� ���������ӳ�ʱΪ5��
            Tcpsocket = new Socket(serverIP, serverPort);    //����DEBUG��Ϣ�п���������Ϣ
            if (!Tcpsocket.isConnected())
                Tcpsocket.connect(new InetSocketAddress(serverIP, serverPort), 1000);

            try {
                Tcpsocket.setSoTimeout(500);
                Tcpsocket.setTcpNoDelay(true);
                TcpSocketOut = (Tcpsocket.getOutputStream());
                TcpSocketIn = (Tcpsocket.getInputStream());

            } catch (IOException e) {
                // TODO Auto-generated catch block
                Log.e("socket", "e1---Tcpsocket==" + Tcpsocket);
                e.printStackTrace();
                mHandler.sendEmptyMessage(4);//todo 处理异常
                mHandler.sendEmptyMessage(10);//todo 处理异常
                return 0x6ff0;
            }

            Log.i("socket", "SAMV Socket" + ":Tcpsocket==" + Tcpsocket + TcpSocketOut + TcpSocketIn);

            return 0;

        } catch (SocketTimeoutException aa) {
            mHandler.sendEmptyMessage(4);//todo 处理异常
            mHandler.sendEmptyMessage(10);//todo 处理异常
            return 0x6ff1;
            // ���ӳ�ʱ ��UI������ʾ��Ϣ
        } catch (IOException e) {
            mHandler.sendEmptyMessage(4);//todo 处理异常
            mHandler.sendEmptyMessage(10);//todo 处理异常
            e.printStackTrace();
            return 0x6ff2;
        }
        // TODO Auto-generated method stub
//			return null;
    }

    /*
     * 发送卡片二进制指令
     *
     * 02 00 24 50 01
     *
     * 00 01 48 41 01 0b 01 06 00 00 00 00 00 01 3d d8 3a 72 08 67 24 81 97 b0 eb e1 69 89 a7 80 b0 5f 90 00
     * a7
     *
     *03
     * 客户端发送协议包一：
        // *  messsage5001SEND===ffffff002c500100014841010b01060000000000013dd83a720867248197b0ebe16989a780b05f900044fefe（发送到远程SocketIP）

        序号	名称	字节数	说明
        1	包头	3	3字节固定值0xff
        2	包长度	2	长度=包头+长度+…+包尾，固定值44字节
        3	5001	2	认证指令，固定值
        4	6002文件	32	32字节6002文件内容
        5	校验字节	1	累加和校验，从长度开始累加，至6002文件结束
        6	包尾	2	固定值0xfe,0xfe
             */
    public void sendsocketdata5001(byte[] cmd, long wait) {
        byte[] subcmd = new byte[34];//5001 6002
        System.arraycopy(cmd, 5, subcmd, 0, subcmd.length);
        Log.e("logtag", HexUtil.encodeHexStr(subcmd));
        byte[] bluecmd = new byte[subcmd.length + 10];
        bluecmd[0] = (byte) 0xFF;
        bluecmd[1] = (byte) 0xFF;
        bluecmd[2] = (byte) 0xFF;
        byte[] len = Util.intTo2byte(subcmd.length + 10);
        bluecmd[3] = len[0];
        bluecmd[4] = len[1];
        bluecmd[5] = cmd[3]; // 0x50;
        bluecmd[6] = cmd[4]; // 0x01;
        int cmdlen = subcmd.length;//34

        System.arraycopy(subcmd, 0, bluecmd, 7, cmdlen);
        Log.e("logtag", HexUtil.encodeHexStr(bluecmd));
        bluecmd[subcmd.length + 7] = getLRC(bluecmd, 3, cmdlen + 4);
        bluecmd[subcmd.length + 8] = (byte) 0xfe;
        bluecmd[subcmd.length + 9] = (byte) 0xfe;
        Log.e("logtag", HexUtil.encodeHexStr(bluecmd));
        Log.e(LOGTAG, "messsage5001SEND===" + Util.bytesToHexString(bluecmd));
        sendcardtran(bluecmd, bluecmd.length);
        socketRead50xx();
    }

    /*认证交互包客户发送协议包二：  run: 20498
     * 发送卡片二进制指令messsage5012SEND===ffffff001450125d7fdab7fce4acf39000adfefe
     *
     * 序号	名称	字节数	说明
        1	包头	3	3字节固定值0xff
        2	包长度	2	长度=包头+长度+…+包尾，固定值15字节,0x0F
        3	5012	2	固定值
        4	随机数指令	5	16进制5字节固定值00 84 00 00 08
        5	校验字节	1	累加和校验，从长度开始累加，至随机数结束
        6	包尾	2	固定值0xfe,0xfe
     */
    public void sendsocketdata5012(final byte[] cmd, long wait) {


        byte[] subcmd = new byte[10];
        System.arraycopy(cmd, 5, subcmd, 0, subcmd.length);

        byte[] bluecmd = new byte[subcmd.length + 10];
        bluecmd[0] = (byte) 0xFF;
        bluecmd[1] = (byte) 0xFF;
        bluecmd[2] = (byte) 0xFF;
        byte[] len = Util.intTo2byte(subcmd.length + 10);
        bluecmd[3] = len[0];
        bluecmd[4] = len[1];
        bluecmd[5] = cmd[3]; // 0x50;
        bluecmd[6] = cmd[4]; // 0x12;
        int cmdlen = subcmd.length;
        System.arraycopy(subcmd, 0, bluecmd, 7, cmdlen);

        bluecmd[subcmd.length + 7] = getLRC(bluecmd, 3, cmdlen + 4);
        bluecmd[subcmd.length + 8] = (byte) 0xfe;
        bluecmd[subcmd.length + 9] = (byte) 0xfe;
        Log.e(LOGTAG, "messsage5012SEND===" + Util.bytesToHexString(bluecmd));
        sendcardtran(bluecmd, bluecmd.length);
        socketRead50xx();

    }

    /*
     * 发送卡片二进制指令
     * 服务器端返回包：
        receivedatamsg===ffffff00125022195fa8de18d2811401fef
        序号	名称	字节数	说明
        1	包头	3	3字节固定值0xff
        2	包长度	2	长度=包头+长度+…+包尾，固定值18字节,0x12
        3	5022	2	固定值
        4	随机数	8	外部认证的8字节随机数
        5	校验字节	1	累加和校验，从长度开始累加，至随机数结束
        6	包尾	2	固定值0xfe,0xfe
     */
    public void sendsocketdata5022(final byte[] cmd, long wait) {

        byte[] subcmd = new byte[10];
        System.arraycopy(cmd, 5, subcmd, 0, subcmd.length);
        byte[] bluecmd = new byte[subcmd.length + 10];
        bluecmd[0] = (byte) 0xFF;
        bluecmd[1] = (byte) 0xFF;
        bluecmd[2] = (byte) 0xFF;
        byte[] len = Util.intTo2byte(subcmd.length + 10);
        bluecmd[3] = len[0];
        bluecmd[4] = len[1];
        bluecmd[5] = cmd[3]; // 0x50;
        bluecmd[6] = cmd[4]; // 0x22;
        int cmdlen = subcmd.length;
        System.arraycopy(subcmd, 0, bluecmd, 7, cmdlen);

        bluecmd[subcmd.length + 7] = getLRC(bluecmd, 3, cmdlen + 4);
        bluecmd[subcmd.length + 8] = (byte) 0xfe;
        bluecmd[subcmd.length + 9] = (byte) 0xfe;
        // SocketUtil.Send(cardinfo, true, false,null, 0, bluecmd);
        // TCPServer.write(bluecmd);
        // TCPServer.read();
        sendcardtran(bluecmd, bluecmd.length);
        socketRead50xx();
    }

    public void sendcardtran(byte[] sendbyte, int length) {
        if (sendbyte != null && (TcpSocketOut != null)) {
            try {

                Log.e(LOGTAG, "send======" + Util.bytesToHexString(sendbyte) + "::length=" + length);
                TcpSocketOut.write(sendbyte, 0, length);
                TcpSocketOut.flush();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                Log.e("timer", "send IOException");
                e.printStackTrace();

                mHandler.obtainMessage(4).sendToTarget();
            }
        }
    }

    private static byte getLRC(byte[] data, int pos, int len) {
        byte lrc = 0;
        lrc = data[pos];
        for (int i = pos + 1; i < len; i++) {
            lrc = (byte) (lrc ^ data[i]);
        }
        return lrc;
    }

    public void socketRead50xx() {
        byte[] arrayMessage = new byte[1500];
        // TODO Auto-generated method stub
        if ((TcpSocketIn != null)) {
            try {
                int nLen = 0;
                Arrays.fill(arrayMessage, (byte) 0);

                Tcpsocket.setSoTimeout(1600);
                nLen = TcpSocketIn.read(arrayMessage);

                if (nLen <= 0) {
                    mHandler.obtainMessage(4).sendToTarget();
                    return;
                }
                byte[] result = new byte[nLen];
                System.arraycopy(arrayMessage, 0, result, 0, nLen);
                Log.e(LOGTAG, "receivedatamsg===" + Util.bytesToHexString(result));

                if ((result.length == 18) && (result[5] == 0x50) && (result[6] == 0x01)) {
                    if ((result[7] == 0x20) && (result[8] == 0x00) && (result[9] == 0x00)
                            && (result[10] == 0x00)) {
                        Log.e("tag", "socketRead50xx: error" );
                        mHandler.obtainMessage(4).sendToTarget();
                        return;
                    }

                    byte[] cardresult = new byte[10];
                    System.arraycopy(result, 7, cardresult, 0, 10);
                    idCardCommunication.sendcardtran5001ByBle(cardresult, 0);
                } else if ((result.length == 15) && (result[5] == 0x50) && (result[6] == 0x12)) {

                    // receivedatamsg===ffffff000f5012200000000091fefe
                    // (1066):
                    // sendtonfc=02000c500100000000008f9c00aefe3203

                    if ((result[7] == 0x00) && (result[8] == 0x00) && (result[9] == 0x00)
                            && (result[10] == 0x00)) {
                        Log.e(LOGTAG, "mHandler.befre(4).sendToTarget();	");
                        mHandler.obtainMessage(4).sendToTarget();
                        return;
                    } else {
                        byte[] cardresult = new byte[7];
                        System.arraycopy(result, 5, cardresult, 0, 7);
                        idCardCommunication.sendcardtran5012ByBle(cardresult);
                    }
                } else if ((result.length == 18) && (result[5] == 0x50) && (result[6] == 0x22)) {
                    if ((result[7] == 0) && (result[8] == 0) && (result[9] == 0) && (result[10] == 0)) {
                        mHandler.obtainMessage(4).sendToTarget();
                        return;
                    }
                    byte[] cardresult = new byte[12];
                    System.arraycopy(result, 5, cardresult, 0, 12);
                    idCardCommunication.sendcardtran5022ByBle(cardresult);
                }
            } catch (Exception e) {
                mHandler.obtainMessage(4).sendToTarget();
                Log.e(LOGTAG, "	e.printStackTrace();");
                e.printStackTrace();
            }
        }

    }

    /**
     * receivedatamsg===ffffff000c60029000fefefe
     * 序号	名称	字节数	说明
     * 1	包头	3	3字节固定值0xff
     * 2	包长度	2	长度=包头+长度+…+包尾，固定值12字节，0x0C
     * 3	6002	2	固定值
     * 4	内容	2	正确0x9000，错误0x6fxx, 错误含义待定
     * 5	校验字节	1	累加和校验，从长度开始累加，至随机数结束
     * 6	包尾	2	固定值0xfe,0xfe
     *
     * @param recData
     */

    public void socketRead_60xx(byte[] recData) {

        byte[] arrayMessage = new byte[1500];

        // TODO Auto-generated method stub
        if ((TcpSocketIn != null)) {
            try {
                int nLen = 0;
                Arrays.fill(arrayMessage, (byte) 0);

                Tcpsocket.setSoTimeout(2000);
                nLen = TcpSocketIn.read(arrayMessage);

                if (nLen <= 0) {
                    mHandler.obtainMessage(4).sendToTarget();
                    return;
                }
                byte[] result = new byte[nLen];
                System.arraycopy(arrayMessage, 0, result, 0, nLen);

                Log.e(LOGTAG, "receivedatamsg===" + Util.bytesToHexString(result));

                if ((result.length == 12) && (result[5] == 0x60) && (result[6] == 0x02)) {
                    mHandler.obtainMessage(0).sendToTarget();
                }
                if ((result.length == 1295) && (result[0] == (byte) 0xAA) && (result[1] == (byte) 0xAA) && (result[2] == (byte) 0xAA)) {
//							mHandler.obtainMessage(4).sendToTarget();
                    System.arraycopy(result, 0, recData, 0, 1295);
                    mHandler.obtainMessage(03, 20, -1, null).sendToTarget();
                }
            } catch (Exception e) {
                mHandler.obtainMessage(4).sendToTarget();
                Log.e(LOGTAG, "	e.printStackTrace();");
                e.printStackTrace();
            }
        }

    }

    public Socket getTcpsocket() {
        return Tcpsocket;
    }

    public void setTcpsocket(Socket tcpsocket) {
        Tcpsocket = tcpsocket;
    }

    public OutputStream getTcpSocketOut() {
        return TcpSocketOut;
    }

    public void setTcpSocketOut(OutputStream tcpSocketOut) {
        TcpSocketOut = tcpSocketOut;
    }

    public InputStream getTcpSocketIn() {
        return TcpSocketIn;
    }

    public void setTcpSocketIn(InputStream tcpSocketIn) {
        TcpSocketIn = tcpSocketIn;
    }

    public IDCardCommunication getIdCardCommunication() {
        return idCardCommunication;
    }

    public void setIdCardCommunication(IDCardCommunication idCardCommunication) {
        this.idCardCommunication = idCardCommunication;
    }

    public MainHandler getmHandler() {
        return mHandler;
    }

    public void setmHandler(MainHandler mHandler) {
        this.mHandler = mHandler;
    }

    /**
     * 2.1二代证密文包解码明文响应包：
     * 序号	名称	字节数	说明
     * 1	包头	3	3字节固定值0xff
     * 2	包长度	2	长度=包头+长度+…+包尾，固定值516字节
     * 3	6002	2	0x60 0x02
     * 4	6002文件	32	32字节6002文件内容
     * 5	6011	2	0x60 0x11
     * 6	6011文件	214	214字节6011文件内容
     * 7	6012	2	0x60 0x12
     * 8	6012文件	256	256字节6002文件内容
     * 9	校验字节	1	累加和校验，从长度开始累加，至6012文件结束
     * 10	包尾	2	固定值0xfe,0xfe
     * 向服务器发送组合完整的6013文件
     *
     * @param out_buf
     * @param cmd
     * @param len
     * @param recv_buf
     * @return
     */
    public int sendNew6013AndReceive(byte[] out_buf, String cmd, int len, byte[] recv_buf) {
        if (len == 0) return 0;
        byte[] subcmd = new byte[len];

//		Log.e("lg", "send0===" + Util.bytesToHexString(out_buf) + "::length=" + len);
        System.arraycopy(out_buf, 0, subcmd, 7, out_buf.length);
        subcmd[0] = (byte) 0xFF;
        subcmd[1] = (byte) 0xFF;
        subcmd[2] = (byte) 0xFF;
        byte[] len1 = Util.intTo2byte(len);
        subcmd[3] = len1[0];
        subcmd[4] = len1[1];
        byte[] cmd1 = Util.hexStringToBytes(cmd);
        subcmd[5] = cmd1[0];
        subcmd[6] = cmd1[1];

        byte check = 0;
        for (int i = 4; i < len - 3; i++)
            check += (byte) subcmd[i];

        subcmd[len - 3] = check;
        subcmd[len - 2] = (byte) 0xFE;
        subcmd[len - 1] = (byte) 0xFE;
        //send1=ffffff040a60135352c1:length=1034
        Log.i(LOGTAG, "send1=" + Util.bytesToHexString(subcmd).substring(0, 20) + ":length=" + len);

        int ReadnLen = 0;
        try {
            sendcardtran(TcpSocketOut, subcmd);
            Tcpsocket.setSoTimeout(1200);
            ReadnLen = TcpSocketIn.read(recv_buf);
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();

            Log.i(LOGTAG, "Recv=" + "SocketException e.printStackTrace()" + e.getMessage());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.i(LOGTAG, "Recv=" + "IOException e.printStackTrace()" + e.getMessage());
        }
        //Recv=1295:aaaaaa96690508000090
        Log.i(LOGTAG, "Recv=" + ReadnLen + ":" + Util.bytesToHexString(recv_buf).substring(0, 20));
        return ReadnLen;
    }

    private void sendcardtran(OutputStream Outflow, byte[] sendbyte) throws IOException {

        if (sendbyte != null && (Outflow != null)) {

            Outflow.write(sendbyte, 0, sendbyte.length);
            Outflow.flush();

        }

    }

    public void CloseTcpsocket() throws IOException {
        if (Tcpsocket != null)
            Tcpsocket.close();
        if (TcpSocketIn != null)
            TcpSocketIn.close();
        if (TcpSocketOut != null)
            TcpSocketOut.close();

    }
}
